package com.test.demo.config;

import com.test.demo.shiro.MyRealm;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.crypto.hash.Md5Hash;
import org.apache.shiro.mgt.SessionsSecurityManager;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.spring.web.config.DefaultShiroFilterChainDefinition;
import org.apache.shiro.spring.web.config.ShiroFilterChainDefinition;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class ShiroConfig {

    //注入自定义的realm，告诉shiro如何获取用户信息来做登录或权限控制
    @Bean
    public Realm realm() {
        MyRealm myRealm = new MyRealm();
        myRealm.setCredentialsMatcher(credentialsMatcher());
        return myRealm;
    }

    //密码加密参数
    //采用算法：Md2Hash,Md5Hash,Sha1Hash,Sha256Hash,Sha384Hash,Sha512Hash
    public static String hashAlgorithmName = Md5Hash.ALGORITHM_NAME;
    //hash次数
    public static int hashIterations = 1;
    //true为密码以hex编码存储，false为密码以base64编码存储，默认是true
    public static boolean storedCredentialsHexEncoded = false;

    // 设置用于匹配密码的CredentialsMatcher
    @Bean
    public HashedCredentialsMatcher credentialsMatcher() {
        HashedCredentialsMatcher hashcredentialsMatcher = new HashedCredentialsMatcher();
        hashcredentialsMatcher.setHashAlgorithmName(hashAlgorithmName);
        hashcredentialsMatcher.setHashIterations(hashIterations);
        hashcredentialsMatcher.setStoredCredentialsHexEncoded(storedCredentialsHexEncoded);
        return hashcredentialsMatcher;
    }

//    @Bean
//    public static DefaultAdvisorAutoProxyCreator getDefaultAdvisorAutoProxyCreator() {
//        DefaultAdvisorAutoProxyCreator creator = new DefaultAdvisorAutoProxyCreator();
//        /**
//         * setUsePrefix(false)用于解决一个奇怪的bug。在引入spring aop的情况下。
//         * 在@Controller注解的类的方法中加入@RequiresRole注解，会导致该方法无法映射请求，导致返回404。
//         * 加入这项配置能解决这个bug
//         */
//        creator.setUsePrefix(true);
//
//        creator.setProxyTargetClass(true);
//        return creator;
//    }

    /**
     * 这里统一做鉴权，即判断哪些请求路径需要用户登录，哪些请求路径不需要用户登录。
     * 这里只做鉴权，不做权限控制，因为权限用注解来做。
     *
     * @return
     */
    @Bean
    public ShiroFilterChainDefinition shiroFilterChainDefinition() {
        DefaultShiroFilterChainDefinition chain = new DefaultShiroFilterChainDefinition();

        /**
         * 这里小心踩坑！我在application.yml中设置的context-path: /api/v1
         * 但经过实际测试，过滤器的过滤路径，是context-path下的路径，无需加上"/api/v1"前缀
         */

        //访问控制
        chain.addPathDefinition("/login", "anon");//可以匿名访问
        chain.addPathDefinition("/401", "anon");//可以匿名访问

//        chain.addPathDefinition("/t4/hello", "anon");//可以匿名访问

//        chain.addPathDefinition("/t4/changePwd", "authc");//需要登录
//        chain.addPathDefinition("/t4/user", "user");//已登录或“记住我”的用户可以访问
//        chain.addPathDefinition("/t4/mvnBuild", "authc,perms[mvn:install]");//需要mvn:build权限
//        chain.addPathDefinition("/t4/gradleBuild", "authc,perms[gradle:build]");//需要gradle:build权限
//        chain.addPathDefinition("/t4/js", "authc,roles[js]");//需要js角色
//        chain.addPathDefinition("/t4/python", "authc,roles[python]");//需要python角色

        // shiro 提供的登出过滤器，访问指定的请求，就会执行登录，默认跳转路径是"/"，或者是"shiro.loginUrl"配置的内容
        // 由于application-shiro.yml中配置了 shiro:loginUrl: /page/401，返回会返回对应的json内容
        // 可以结合/user/login和/t1/js接口来测试这个/t4/logout接口是否有效
        chain.addPathDefinition("/t4/logout", "anon,logout");

        //其它路径均需要登录
        chain.addPathDefinition("/**", "authc");
        return chain;
    }


    // 配置security并设置userReaml，避免xxxx required a bean named 'authorizer' that could not be found.的报错
    @Bean
    public SessionsSecurityManager securityManager() {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setRealm(realm());
        return securityManager;
    }


    /**
     * *
     * 开启Shiro的注解(如@RequiresRoles,@RequiresPermissions),需借助SpringAOP扫描使用Shiro注解的类,并在必要时进行安全逻辑验证
     * *
     * 配置以下两个bean(DefaultAdvisorAutoProxyCreator(可选)和AuthorizationAttributeSourceAdvisor)即可实现此功能
     * * @return
     */
//    @Bean
//    @DependsOn({"lifecycleBeanPostProcessor"})
//    public DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator() {
//        DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
//        advisorAutoProxyCreator.setProxyTargetClass(true);
//        return advisorAutoProxyCreator;
//    }

//    @Bean
//    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor() {
//        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
//        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager());
//        return authorizationAttributeSourceAdvisor;
//    }

//    @Bean
//    public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
//        return new LifecycleBeanPostProcessor();
//    }


//    @Bean
//    public SecurityManager securityManager() {

//        DefaultWebSecurityManager defaultSecurityManager = new DefaultWebSecurityManager();
    //配置鉴权授权
//        defaultSecurityManager.setRealm(realm());

    // 自定义缓存实现(权限数据) 使用redis
//        defaultSecurityManager.setCacheManager(cacheManager());
    // 自定义session管理(session信息) 使用redis
//        defaultSecurityManager.setSessionManager(sessionManager());

    //注入Cookie记住我管理器
//        defaultSecurityManager.setRememberMeManager(rememberMeManager());

//        return defaultSecurityManager;
//    }

}